001    /**
002     * Created by IntelliJ IDEA.
003     * User: Wei Wang
004     * Date: Jan 15, 2003
005     * Time: 1:10:46 PM
006     */
007    
008    package EVolve.util.sourcebrowser;
009    
010    import EVolve.Scene;
011    import javax.swing.*;
012    import javax.swing.event.*;
013    import java.io.*;
014    import java.awt.*;
015    import java.awt.event.*;
016    import java.util.ArrayList;
017    
018    public class SourceBrowser implements Cloneable{
019        private JInternalFrame window;
020        private JDesktopPane desktop;
021        private String target;
022        private ArrayList textBuffer;
023        private int line_no = 0;
024        private int caretPosition = 0;
025        private JPopupMenu popup;
026        private JMenuItem itemFind, itemFindNext, itemFindPrevious;
027        private JTextArea textArea;
028        private String loadedFilename;
029    
030        public SourceBrowser() {
031            window = null;
032            desktop = Scene.getUIManager().getDesktop();
033            textBuffer = new ArrayList();
034            popup = new JPopupMenu();
035            loadedFilename = null;
036    
037            itemFind = new JMenuItem("Find...");
038            itemFind.setMnemonic(KeyEvent.VK_F);
039            itemFind.addActionListener(new ActionListener() {
040                public void actionPerformed(ActionEvent e) {
041                    target = (String)JOptionPane.showInputDialog(Scene.getFrame(), "Input string to be find:", "Find...", JOptionPane.QUESTION_MESSAGE, null, null, target);
042                    caretPosition = 0;
043                    find(target, 0, textBuffer.size(),false);
044                }
045            });
046            popup.add(itemFind);
047    
048            itemFindNext = new JMenuItem("Find Next");
049            itemFindNext.setMnemonic(KeyEvent.VK_N);
050            itemFindNext.addActionListener(new ActionListener() {
051                public void actionPerformed(ActionEvent e) {
052                    findNext(target);
053                }
054            });
055            popup.add(itemFindNext);
056    
057            itemFindPrevious = new JMenuItem("Find Previous");
058            itemFindPrevious.setMnemonic(KeyEvent.VK_P);
059            itemFindPrevious.addActionListener(new ActionListener() {
060                public void actionPerformed(ActionEvent e) {
061                    findPrevious(target);
062                }
063            });
064            popup.add(itemFindPrevious);
065        }
066    
067        public void showSourceFile(String entityName) {
068            if (entityName == null) return;
069    
070            String className = extractClassName(entityName);
071            String fileName = ClassExplorer.v().getSourceFileFromClass(className);
072    
073            if (fileName == null) {
074                return;
075            }
076    
077            if (window == null) {
078                window = new JInternalFrame(entityName,true, true, true, true);
079                window.addInternalFrameListener(new InternalFrameAdapter() {
080                    public void internalFrameClosing(InternalFrameEvent e) {
081                        window = null;
082                    }
083                });
084                window.setClosable(true);
085                window.setBounds(desktop.getSize().width - 600, 0, 600, 300);
086                window.setResizable(true);
087                desktop.add(window);
088                textArea = new JTextArea();
089            }
090            window.moveToFront();
091            window.setVisible(true);
092            if (fileName.equals(loadedFilename)) {
093                int position = find(target,0,textBuffer.size(),true);
094                textArea.setCaretPosition(position);
095            } else {
096                window.getContentPane().removeAll();
097                window.getContentPane().add(loadSourceFile(fileName));
098            }
099            window.setTitle(entityName);
100        }
101    
102        private JScrollPane loadSourceFile(String fileName) {
103            textArea = new JTextArea();
104            line_no = 0;
105    
106            try {
107                RandomAccessFile file = new RandomAccessFile(fileName,"r");
108                textBuffer.clear();
109    
110                String line = file.readLine();
111                while (line!=null) {
112                    textBuffer.add(line + "\n");
113                    textArea.append(line + "\n");
114                    line = file.readLine();
115                }
116                caretPosition  = 0;
117                int position = find(target,0,textBuffer.size(),true);
118                if (position!=-1) textArea.setCaretPosition(position);
119                addPopupTrigger(textArea);
120            } catch (IOException e) {
121                Scene.showErrorMessage("Error occurred when accessing source file:\n" +
122                                       "\""+fileName+"\".");
123            }
124    
125    
126            return new JScrollPane(textArea);
127        }
128    
129        private String extractClassName(String entityName) {
130            int index = entityName.lastIndexOf('(');
131            target = "";
132    
133            if (index == -1) {
134                /* no '(' found, this is not a method/location entity */
135                return entityName;
136            }
137            String className = entityName.substring(0,index);
138            index = className.lastIndexOf('.');
139    
140            if (index != -1) {
141                className = entityName.substring(0,index);
142                target = entityName.substring(index+1,entityName.indexOf('('));
143            }
144    
145            return className;
146        }
147    
148        private boolean isEntity(String line) {
149            if ((line!=null)&&(line.indexOf('(')!=-1))
150                //&&
151                //((line.indexOf("public") != -1) ||
152                //(line.indexOf("private") != -1) ||
153                //(line.indexOf("protected") != -1))) {
154            {
155                return true;
156            }
157    
158            return false;
159        }
160    
161        private int find(String target, int start_line_no, int end_line_no, boolean target_is_entity) {
162            String line;
163            boolean found = false;
164    
165            for (int i=start_line_no; i<end_line_no; i++) {
166                line = (String)textBuffer.get(i);
167                if ((line.indexOf(target) != -1) && ((!target_is_entity) || isEntity(line))) {
168                    found = true;
169                    line_no = i;
170                    textArea.setCaretPosition(caretPosition);
171                    break;
172                }
173                caretPosition += line.length();
174            }
175    
176            if (!found) {
177                Scene.showErrorMessage("String \""+target+"\" is not found.");
178            }
179    
180            return found ? caretPosition : -1;
181        }
182    
183        private int findNext(String target) {
184            caretPosition = 0;
185    
186            for (int i=0; i<=line_no; i++) {
187                caretPosition += ((String)textBuffer.get(i)).length();
188            }
189    
190            return find(target, line_no+1, textBuffer.size(), false);
191        }
192    
193        private int findPrevious(String target) {
194            String line;
195            boolean found = false;
196    
197            caretPosition = 0;
198    
199            for (int i=0; i<line_no-1; i++) {
200                caretPosition += ((String)textBuffer.get(i)).length();
201            }
202    
203            for (int i=line_no - 1; i>=0; i--) {
204                line = (String)textBuffer.get(i);
205                if (line.indexOf(target) != -1) {
206                    found = true;
207                    textArea.setCaretPosition(caretPosition);
208                    line_no = i;
209                    break;
210                }
211                caretPosition -= line.length();
212            }
213    
214            if (!found) {
215                Scene.showErrorMessage("String \""+target+"\" is not found.");
216            }
217    
218            return found ? caretPosition : -1;
219        }
220    
221        protected void addPopupTrigger(Component component) {
222            component.addMouseListener(new MouseAdapter() {
223                public void mouseReleased(MouseEvent e) {
224                    if (e.isPopupTrigger()) {
225                        showPopup(e);
226                    }
227                }
228    
229                public void mousePressed(MouseEvent e) {
230                    if (e.isPopupTrigger()) {
231                        showPopup(e);
232                    }
233                }
234            });
235        }
236    
237        private void showPopup(MouseEvent e) {
238            int mouseX = e.getX();
239            int mouseY = e.getY();
240            Rectangle rect = e.getComponent().getBounds();
241            Rectangle rect2 = popup.getBounds();
242            int posX= mouseX, posY = mouseY;
243            if (mouseY+rect2.height > rect.height)
244                posY = posY - rect2.height;
245            if (mouseX+rect2.width>rect.width)
246                posX = posX - rect2.width;
247                popup.show(e.getComponent(), posX, posY);
248        }
249    
250        public Object clone() {
251            SourceBrowser o = null;
252            try {
253                o = (SourceBrowser)super.clone();
254            } catch (CloneNotSupportedException e) {
255                e.printStackTrace();
256                return null;
257            }
258            o.target = target;
259            o.textBuffer = (ArrayList)textBuffer.clone();
260            o.loadedFilename = loadedFilename;
261            return o;
262        }
263    }